package com.xnyzc.lhy.order.service.impl.work;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xnyzc.lhy.common.component.config.security.TokenUser;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.constant.MessageConstant;
import com.xnyzc.lhy.common.constant.MqConstant;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.entity.DiDiRv;
import com.xnyzc.lhy.common.entity.Qw;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.entity.netty.NettyDriverOrderInfo;
import com.xnyzc.lhy.common.entity.order.OaDOrderCharteredDetail;
import com.xnyzc.lhy.common.exception.DiDiException;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.global.Configuration;
import com.xnyzc.lhy.common.penum.EDiDiErrorCode;
import com.xnyzc.lhy.common.penum.EDriverStatus;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.cms.EVehicleType;
import com.xnyzc.lhy.common.penum.driver.EServiceFraction;
import com.xnyzc.lhy.common.penum.order.EBillType;
import com.xnyzc.lhy.common.penum.order.EOrderChannelType;
import com.xnyzc.lhy.common.penum.order.EOrderStatus;
import com.xnyzc.lhy.common.penum.work.EAcceptOrderType;
import com.xnyzc.lhy.common.penum.work.EWorkRecordType;
import com.xnyzc.lhy.common.util.*;
import com.xnyzc.lhy.mis.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.TokenUtil;
import com.xnyzc.lhy.order.entity.common.order.OrderCommon;
import com.xnyzc.lhy.order.entity.driver.wallet.OaDWallet;
import com.xnyzc.lhy.order.entity.gps.OaDVehicleGps;
import com.xnyzc.lhy.order.entity.order.OaCOrder;
import com.xnyzc.lhy.order.entity.order.OaCOrderPersonal;
import com.xnyzc.lhy.order.entity.order.OaDOrder;
import com.xnyzc.lhy.order.entity.param.cms.PageDto;
import com.xnyzc.lhy.order.entity.param.order.CharteredDetailsParam;
import com.xnyzc.lhy.order.entity.param.order.DisBookingOrderParam;
import com.xnyzc.lhy.order.entity.param.order.OaSysOrderDetails;
import com.xnyzc.lhy.order.entity.param.synchronization.StatusCallbackParam;
import com.xnyzc.lhy.order.entity.param.user.message.DriverMessageParam;
import com.xnyzc.lhy.order.entity.system.OaSysGlobalConfig;
import com.xnyzc.lhy.order.entity.system.OaSysUser;
import com.xnyzc.lhy.order.entity.user.OaDUser;
import com.xnyzc.lhy.order.entity.user.OaDUserInfo;
import com.xnyzc.lhy.order.entity.user.OaDUserOffice;
import com.xnyzc.lhy.order.entity.vehicle.OaSysVehicle;
import com.xnyzc.lhy.order.entity.work.OaDWorkRecord;
import com.xnyzc.lhy.order.entity.work.OaDWorkStatistics;
import com.xnyzc.lhy.order.feign.didi.IDidiService;
import com.xnyzc.lhy.order.mapper.driver.wallet.OaDWalletMapper;
import com.xnyzc.lhy.order.mapper.order.OaCOrderPersonalMapper;
import com.xnyzc.lhy.order.mapper.order.OaDOrderCharterDetailMapper;
import com.xnyzc.lhy.order.mapper.order.OaDOrderMapper;
import com.xnyzc.lhy.order.mapper.order.OaSysOrderDetailsMapper;
import com.xnyzc.lhy.order.mapper.sidebar.OaSysOfficeMapper;
import com.xnyzc.lhy.order.mapper.system.OaSysGlobalConfigMapper;
import com.xnyzc.lhy.order.mapper.system.OaSysUserMapper;
import com.xnyzc.lhy.order.mapper.user.OaDUserInfoMapper;
import com.xnyzc.lhy.order.mapper.user.OaDUserMapper;
import com.xnyzc.lhy.order.mapper.user.OaDUserOfficeMapper;
import com.xnyzc.lhy.order.mapper.user.message.OaSysMessageMapper;
import com.xnyzc.lhy.order.mapper.vehicle.OaSysVehicleMapper;
import com.xnyzc.lhy.order.mapper.work.OaDWorkRecordMapper;
import com.xnyzc.lhy.order.mapper.work.OaDWorkStatisticsMapper;
import com.xnyzc.lhy.order.mo.OrderLogMo;
import com.xnyzc.lhy.order.mq.MqOrderProducer;
import com.xnyzc.lhy.order.service.work.IOaDWorkStatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;

import static com.xnyzc.lhy.common.constant.MqConstant.LOG_OPERATE_ORDER;

/**
 * <p>
 * 表（日统计，实时更新） 服务实现类
 * </p>
 *
 * @author zhuyubin
 * @since 2019-08-02
 */
@Slf4j
@Service
@Transactional
public class OaDWorkStatisticsServiceImpl extends ServiceImpl<OaDWorkStatisticsMapper, OaDWorkStatistics> implements IOaDWorkStatisticsService {

    private static final String ZEOR = "0";

    /**
     * 控制行程录音开关
     * 0 -- 关闭  1 -- 开始
     */
    @Value("${global.startRecord}")
    private Integer startRecord;

    @Autowired
    private OaDWorkStatisticsMapper oaDWorkStatisticsMapper;
    @Autowired
    private OaDUserMapper oaDUserMapper;
    @Autowired
    private RedisCommon redisCommon;
    @Autowired
    private OrderCommon orderCommon;
    @Autowired
    private OaDWorkRecordMapper oaDWorkRecordMapper;
    @Autowired
    private OaDOrderMapper oaDOrderMapper;
    @Autowired
    private OaDUserInfoMapper oaDUserInfoMapper;
    @Autowired
    private OaCOrderPersonalMapper oaCOrderPersonalMapper;
    @Autowired
    private OaSysMessageMapper oaSysMessageMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IDidiService iDidiService;
    @Autowired
    private MqOrderProducer producer;
    @Autowired
    private OaSysUserMapper oaSysUserMapper;
    @Autowired
    private OaDUserOfficeMapper oaDUserOfficeMapper;
    @Autowired
    private OaSysVehicleMapper oaSysVehicleMapper;
    @Autowired
    private OaDWalletMapper oaDWalletMapper;
    @Autowired
    private OaSysOrderDetailsMapper oaSysOrderDetailsMapper;

    @Autowired
    private OaSysUserMapper userMapper;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private OaSysOfficeMapper oaSysOfficeMapper;
    @Autowired
    private OaSysGlobalConfigMapper oaSysGlobalConfigMapper;
    @Autowired
    private OaDOrderCharterDetailMapper oaDOrderCharterDetailMapper;


    /**
     * 包车订单指派司机
     *
     * @param charteredDetailsParam
     * @return
     */
    @Override
    public Rv assignCharterDriver(CharteredDetailsParam charteredDetailsParam) {
        if (CheckUtil.objIsEmpty(charteredDetailsParam)) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        OaDUserInfo driverInfo = null;
        OaDUser driver = null;
        for (OaDOrderCharteredDetail charteredDetail : charteredDetailsParam.getCharteredDetailsParam()) {
            Long driverId = Long.valueOf(charteredDetail.getDriverId());
            String orderId = charteredDetail.getOrderNo();
            if (CheckUtil.objIsNotEmpty(driverId) && driverId > 0) {
                driver = oaDUserMapper.selectOne(Qw.create().eq(OaDUser.DRIVER_ID, driverId));
                driverInfo = oaDUserInfoMapper.selectOne(Qw.create().eq(OaDUserInfo.DRIVER_ID, driverId));
            } else {
                return Rv.error(EErrorCode.argCheckErr);
            }
            if (driver.getIsBlocked() == 1) {
                return Rv.error(EErrorCode.driverIsBlacklist);
            }
            if (driverInfo == null) {
                return Rv.error(EErrorCode.argCheckErr);
            }
            OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
            if (personal == null) {
                return Rv.error(EErrorCode.argCheckErr);
            }
            QueryWrapper<OaDOrderCharteredDetail> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(OaDOrderCharteredDetail.ORDER_NO, charteredDetail.getOrderNo())
                    .eq(OaDOrderCharteredDetail.ORDER_DATE, charteredDetail.getOrderDate());
            OaDOrderCharteredDetail oaDOrderCharteredDetail = oaDOrderCharterDetailMapper.selectOne(queryWrapper);
            if (CheckUtil.objIsNotEmpty(oaDOrderCharteredDetail)) {
                charteredDetail.setId(oaDOrderCharteredDetail.getId());
                //向平台和司机发送确认消息
                Rv rv = handleCharterOrder(personal, driverInfo, 0, charteredDetail);
                if (rv.getCode() == EErrorCode.success.getValue()) {
                    UpdateWrapper<OaDOrderCharteredDetail> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq(OaDOrderCharteredDetail.ORDER_NO, charteredDetail.getOrderNo())
                            .eq(OaDOrderCharteredDetail.ORDER_DATE, charteredDetail.getOrderDate());
                    int i = oaDOrderCharterDetailMapper.update(charteredDetail, updateWrapper);
                    if (i < 1) {
                        throw new PangException(EErrorCode.orderFailure);
                    }
                    //删除可能存在的抢单信息
                    String bookingKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + orderId;
                    String hallKey = RedisPrefixConstant.ORDER_TC_HALL + personal.getCityId();
                    redisCommon.delFromZSet(hallKey, bookingKey);
                    redisCommon.remove(bookingKey);
                    //向司机发送通知
                    producer.sendMsg(personal, MqConstant.NOTICE_DIS_ORDER);
                    //向司机发短信
                    personal.setDriverId(driverInfo.getDriverId());
                    producer.sendMsg(personal, MqConstant.NEW_ORDER_TO_DRIVER);
                    //将日志发送至mq
                    operateLog(personal, TokenUtil.getTokenUser(), "将订单：" + personal.getOrderNo() +
                            "用车日期为：" + DateUtil.getStringDateShort(charteredDetail.getOrderDate()) + "指定给了司机：" + driver.getDriverName(), null);
                } else {
                    return Rv.wrap();
                }
            }
        }
        return Rv.wrap(EErrorCode.success);
    }

    /**
     * 获取司机信息
     *
     * @param driverId 司机id
     * @param tag      租户
     * @return
     */
    @Override
    public Map<String, Object> getWorkStatistics(Long driverId, String tag, Integer userType) {
        Date date = new Date();
        Timestamp dayStartTime = DateUtil.getDayStartTime(date);
        Timestamp dayEndTime = DateUtil.getDayEndTime(date);
        BigDecimal zero = new BigDecimal(ZEOR);
        long tokenUserId = TokenUtil.getTokenUserId();
        log.info("开始获取司机信息：{}", tokenUserId);
        // 司机日统计redis key
        String workStatisticsRedisKey = String.format("%s%s", RedisPrefixConstant.WORK_OA_D_WORK_STATISTICS, driverId);
        String workStatisticsJsonStr = redisCommon.getStr(workStatisticsRedisKey);
        // 先从redis中查，redis中没有去数据库查
        OaDWorkStatistics oaDWorkStatistics;
        if (CheckUtil.objIsNotEmpty(workStatisticsJsonStr)) {
            oaDWorkStatistics = JSON.parseObject(workStatisticsJsonStr, OaDWorkStatistics.class);
        } else {
            oaDWorkStatistics = this.getWork(driverId, tag);
        }
        // 初始化响应字段
        Map<String, Object> map = new HashMap<>(16);
        map = this.initWorkStatisticsMap(map);
        //获取司机信息
        Map<String, Object> stringObjectMap = oaDUserMapper.queryDriverInfoByDriverId(tokenUserId);
        if (CheckUtil.mapIsEmpty(stringObjectMap)) {
            log.error("未获取到用户信息!");
            return map;
        }
        if (stringObjectMap.containsKey("tid")) {
            map.put("tid", stringObjectMap.get("tid").toString());
        }
        if (stringObjectMap.containsKey("driverPhone")) {
            map.put("driverPhone", stringObjectMap.get("driverPhone").toString());
        }
        //获取车牌号
        if (stringObjectMap.containsKey("vehNo")) {
            map.put("vehNo", stringObjectMap.get("vehNo").toString());
        }
        //获取司机头像
        if (stringObjectMap.containsKey("avatarFileId")) {
            map.put("avatarFileId", stringObjectMap.get("avatarFileId").toString());
        }
        //获取司机姓名
        if (stringObjectMap.containsKey("driverName")) {
            map.put("driverName", stringObjectMap.get("driverName").toString());
        }
        //获取司机所在城市
        if (stringObjectMap.containsKey("cityId")) {
            map.put("cityId", stringObjectMap.get("cityId").toString());
        }
        //获取司机所在供应商
        if (stringObjectMap.containsKey("officeId")) {
            map.put("officeId", stringObjectMap.get("officeId"));
        }
        //获取车辆服务类型
        if (stringObjectMap.containsKey("vehicleType")) {
            map.put("vehicleType", stringObjectMap.get("vehicleType").toString());
        }

        //判断是否开始接单中
        if (stringObjectMap.containsKey("acceptancOrderStatus")) {
            if (stringObjectMap.get("acceptancOrderStatus").equals(1)) {
                map.put("acceptOrderType", EAcceptOrderType.no.getType());
                map.put("acceptOrderTypeName", EAcceptOrderType.no.getValue());
            }
        }

        //获取订单信息
        //-----------------------------------------------
        //获取订单信息,并且判断是否应该解锁司机
        getOrderInfo(map, tokenUserId, stringObjectMap);
        //-----------------------------------------------
        log.info("司机:{},已获取司机订单：{}", tokenUserId, map.toString());
        List<OaSysGlobalConfig> oaSysGlobalConfigs = oaSysGlobalConfigMapper.selectList(Wrappers.<OaSysGlobalConfig>lambdaQuery().eq(OaSysGlobalConfig::getTag, TokenUtil.getTag()));
        if (oaSysGlobalConfigs.size() == 1) {
            if (CheckUtil.objIsNotEmpty(oaSysGlobalConfigs.get(0).getGouldServiceId())) {
                map.put("serviceId", oaSysGlobalConfigs.get(0).getGouldServiceId().toString());
            }
        }
        // 计算今日完成订单数量
        // 已完成订单状态集合
        List<Integer> orderStatusList = new ArrayList<>();
        orderStatusList.add(EOrderStatus.paymented.getType());
        orderStatusList.add(EOrderStatus.normalOrderPendingPayment.getType());
        orderStatusList.add(EOrderStatus.normalOrderPendingPayment.getType());
        List<OaDOrder> oaDOrders = oaDOrderMapper.selectList(Wrappers.<OaDOrder>lambdaQuery()
                .eq(OaDOrder::getDriverId, driverId)
                .in(OaDOrder::getOrderStatus, orderStatusList)
                .ge(OaDOrder::getFinishTime, new Date(dayStartTime.getTime()))
                .le(OaDOrder::getFinishTime, new Date(dayEndTime.getTime())));
        Integer dayOrderNumber = oaDOrders.size();
        // 今日收入
        BigDecimal dayTotalCost = zero;
        if (CheckUtil.collectionIsNotEmpty(oaDOrders)) {
            for (OaDOrder oaDOrder : oaDOrders) {
                BigDecimal drawFee = oaDOrder.getDrawFee();
                if (CheckUtil.objIsEmpty(drawFee)) {
                    continue;
                }
                dayTotalCost = dayTotalCost.add(drawFee);
            }
        }
        map.put("dayTotalCost", dayTotalCost.toString());
        map.put("dayOrderNumber", String.valueOf(dayOrderNumber));
        // 接单记录
        List<OaDWorkRecord> oaDWorkRecordList = oaDWorkRecordMapper.selectList(
                Wrappers.<OaDWorkRecord>lambdaQuery()
                        .eq(OaDWorkRecord::getTag, tag)
                        .eq(OaDWorkRecord::getDriverId, driverId)
                        .ge(OaDWorkRecord::getCreateTime, new Date(dayStartTime.getTime()))
                        .le(OaDWorkRecord::getCreateTime, new Date(dayEndTime.getTime())));

        log.info("司机:{},开始获取在线时长：{}", tokenUserId, map.toString());
        // 在线时长
        Long min = 0L;
        if (CheckUtil.objIsNotEmpty(oaDWorkRecordList)) {
            for (int i = 0; i < oaDWorkRecordList.size(); i++) {
                OaDWorkRecord oaDWorkRecord = oaDWorkRecordList.get(i);
                // 开始接单时间
                Date startTime = oaDWorkRecord.getStartTime();
                if (CheckUtil.objIsEmpty(startTime)) {
                    continue;
                }
                // 结束接单时间
                Date endTime = oaDWorkRecord.getEndTime();
                if (CheckUtil.objIsEmpty(endTime)) {
                    continue;
                }
                min = min + DateUtil.dateSubtractLong(startTime, endTime);
            }
            OaDWorkRecord oaDWorkRecord = oaDWorkRecordList.get(oaDWorkRecordList.size() - 1);
            if (CheckUtil.objIsEmpty(oaDWorkRecord.getEndTime())) {
                Date startTime = oaDWorkRecord.getStartTime();
                if (CheckUtil.objIsNotEmpty(startTime)) {
                    min = min + DateUtil.dateSubtractLong(startTime, date);

                }
            }
        }
        if (CheckUtil.objIsNotEmpty(oaDWorkStatistics)) {
            // 更新接单时长
            try {
                oaDWorkStatistics.setDayOrderTime(Integer.valueOf(min.toString()));
            } catch (Exception e) {
                log.error("在线时长类型转换错误");
                log.info(e.getMessage());
            }
            oaDWorkStatistics.setDayOrderNumber(dayOrderNumber);
            oaDWorkStatistics.setDayTotalCost(dayTotalCost.toString());
            oaDWorkStatistics.setUpdateUser(driverId);
            oaDWorkStatistics.setUpdateTime(date);
            // 司机有打卡记录
            if (CheckUtil.objIsNotEmpty(workStatisticsJsonStr)) {
                // 更新redis
                redisCommon.set(workStatisticsRedisKey, JSON.toJSONString(oaDWorkStatistics));
            }
            // 没有打卡记录
            else {
                // 更新数据库
                oaDWorkStatisticsMapper.updateById(oaDWorkStatistics);
            }
        }
        log.info("司机:{},已完成更新在线时长：{}", tokenUserId, map.toString());
        // 分钟转小时保留一位小数
        String minStr = min.toString();
        if (!ZEOR.equals(minStr)) {
            BigDecimal six = new BigDecimal("60");
            BigDecimal mainBig = new BigDecimal(minStr);
            BigDecimal h = mainBig.divide(six, 1, BigDecimal.ROUND_HALF_UP);
            String hStr = h.toString();
            log.info("司机:{},开始截取服务时长：{}", tokenUserId, hStr);
            if (hStr.contains(".0")) {
                String[] hSplit = hStr.split("\\.");
                map.put("dayServiceTime", String.format("%sh", hSplit[0]));
            } else {
                map.put("dayServiceTime", String.format("%sh", h));
            }
        } else {
            map.put("dayServiceTime", "0h");
        }
        return map;
    }


    /**
     * 该方判断是否应该解锁司机还是放回当前当前订单信息
     *
     * @param map
     * @param driverId
     * @param stringObjectMap
     */
    public void getOrderInfo(Map<String, Object> map, Long driverId, Map<String, Object> stringObjectMap) {
        //判断是否开始接单中
        if (stringObjectMap.containsKey("currentOrderNo")) {
            String orderNo = stringObjectMap.get("currentOrderNo").toString();
            if (CheckUtil.strIsNotEmpty(orderNo)) {
                String orderJson = redisCommon.getStr(RedisPrefixConstant.ORDER_OA_D_ORDER + orderNo);
                OaCOrder oaCOrder = null;
                //FIXME 不确定ORDER_OA_D_ORDER 里是否存在orderType
                if (CheckUtil.objIsEmpty(orderJson)) {
                    oaCOrder = orderCommon.selectOn(orderNo);
                } else {
                    oaCOrder = JSON.parseObject(orderJson, OaCOrder.class);
                }
                //如果为空不需要进行检验
                if (CheckUtil.objIsEmpty(oaCOrder)) {
                    return;
                }
                //因为有几率存在抢单失败,但是未释放司机的问题,所以在此做一个释放.....实属时间紧张,无奈啊
                //判断当前订单状态释放,因为释放司机
                EOrderStatus orderStatus = EOrderStatus.findById(oaCOrder.getOrderStatus());
                if (CheckUtil.objIsEmpty(orderStatus)) {
                    //如果订单状态都为空,还返回干啥,直接解锁司机
                    OaDUserInfo oaDUserInfo = oaDUserInfoMapper.selectOne(Qw.create().eq(OaDUserInfo.DRIVER_ID, driverId));
                    if (CheckUtil.objIsNotEmpty(oaDUserInfo)) {
                        log.info("DRIVER_HISTORY 司机被释放了失败,司机当前订单号:[{}],当前订单状态:[{}],司机ID:[{}]", orderNo, orderStatus, driverId);
                        oaDUserInfo.setCurrentOrderNo("");
                        oaDUserInfo.setIsOrder(0);
                        oaDUserInfoMapper.updateById(oaDUserInfo);
                    }
                    return;
                }
                //判断当前状态是否应该释放司机
                boolean freedDriver = EOrderStatus.isFreedDriver(orderStatus);
                if (freedDriver) {
                    //释放司机
                    OaDUserInfo oaDUserInfo = oaDUserInfoMapper.selectOne(Qw.create().eq(OaDUserInfo.DRIVER_ID, driverId));
                    if (CheckUtil.objIsNotEmpty(oaDUserInfo)) {
                        log.info("DRIVER_HISTORY 司机被释放了失败,司机当前订单号:[{}],当前订单状态:[{}],司机ID:[{}]", orderNo, orderStatus, driverId);
                        oaDUserInfo.setCurrentOrderNo("");
                        oaDUserInfo.setIsOrder(0);
                        oaDUserInfoMapper.updateById(oaDUserInfo);
                    }
                    return;
                }
                /**
                 * 查询oadorder表当前订单
                 */
                if (oaCOrder.getOrderType() == 7) {
                    OaDOrder oaDOrder = oaDOrderMapper.selectOne(Qw.create().eq(OaDOrder.ORDER_NO, orderNo).eq(OaDOrder.ORDER_STATUS, EOrderStatus.duringTrip.getType())
                            .select(OaDOrder.APPOINTMENT_TIME));
                    if (oaDOrder != null) {
                        map.put("appointmentTime", oaDOrder.getAppointmentTime());
                    } else {
                        log.error("无法查询到当前司机订单：[{}]", orderNo);
                    }
                }
                //不需要释放司机,返回订单相关信息
                map.put("orderNo", orderNo);
                map.put("orderStatus", oaCOrder.getOrderStatus());
                map.put("currentMileage", oaCOrder.getMilageDistance());
                map.put("lastTime", oaCOrder.getLastTime());
                map.put("totalFee", oaCOrder.getDrawFee());
                map.put("orderType", oaCOrder.getOrderType());
                return;
            }
        }
    }

    @Override
    public List<Map<String, Object>> getHomeMessage(PageDto pageDto) {

        log.info("------------******************-------------页码：{},页数：{}----------------******************-------------------", pageDto.getPage(), pageDto.getLimit());

        Long driverId = TokenUtil.getTokenUserId();

        // 保存日活司机数据
        QueryWrapper<OaDUserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaDUserInfo.DRIVER_ID, driverId);
        queryWrapper.select(OaDUserInfo.REGISTER_CITY_ID);
        OaDUserInfo oaDUserInfo = oaDUserInfoMapper.selectOne(queryWrapper);

        if (CheckUtil.objIsEmpty(oaDUserInfo)) {
            throw PangException.create(EErrorCode.userFieldError);
        }

        Map<String, String> driverActive = new HashMap<>(2);
        driverActive.put("driverId", driverId.toString());
        driverActive.put("adcode", oaDUserInfo.getRegisterCityId().toString());

        redisTemplate.opsForSet().add(RedisPrefixConstant.DRIVER_ACTIVE, driverActive);

        DriverMessageParam driverMessageParam = new DriverMessageParam();
        driverMessageParam.setDriverId(driverId);
        driverMessageParam.setPage(pageDto.getPage());
        driverMessageParam.setLimit(pageDto.getLimit());

        // 获取司机未读消息
        List<Map<String, Object>> oaSysMessages = oaSysMessageMapper.queryNewMessage(driverMessageParam);

        return oaSysMessages;
    }

    /**
     * 获取当天的工作统计
     *
     * @param driverId
     * @param tag
     * @return
     */
    @Override
    public OaDWorkStatistics getWork(Long driverId, String tag) {
        // 司机工作统计表（日统计，实时更新）
        List<OaDWorkStatistics> oaDWorkStatisticsList = oaDWorkStatisticsMapper.selectList(
                Wrappers.<OaDWorkStatistics>lambdaQuery()
                        .eq(OaDWorkStatistics::getTag, tag)
                        .eq(OaDWorkStatistics::getDriverId, driverId)
                        .orderByDesc(OaDWorkStatistics::getCreateTime));
        if (CheckUtil.objIsEmpty(oaDWorkStatisticsList)) {
            return null;
        }
        return oaDWorkStatisticsList.get(0);
    }

    /**
     * 初始化map
     *
     * @param map
     * @return
     */
    private Map<String, Object> initWorkStatisticsMap(Map<String, Object> map) {
        map.put("totalServiceScore", EServiceFraction.serviceFraction.getValue());
        map.put("dayTotalCost", "0");
        map.put("dayOrderNumber", "0");
        map.put("dayServiceTime", "0");
        map.put("avatarFileId", "");
        map.put("driverId", String.valueOf(TokenUtil.getTokenUserId()));
        map.put("driverName", "");
        map.put("isWorkRecord", EWorkRecordType.no.getType());
        map.put("isWorkRecordName", EWorkRecordType.no.getValue());
        map.put("acceptOrderType", EAcceptOrderType.yes.getType());
        map.put("acceptOrderTypeName", EAcceptOrderType.yes.getValue());
        map.put("orderNo", "");
        map.put("redisKey", RedisPrefixConstant.GPS_VEH_KEY_PREFIX + TokenUtil.getTokenUserId());
        map.put("orderStatus", 0);
        map.put("currentMileage", "0");
        map.put("lastTime", new Date());
        map.put("isPrivate", "0");
        map.put("privateMileage", "0");
        map.put("startRecord", startRecord);
        return map;
    }

    @Override
    public Rv throwOrderToHall(String orderId) {
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
        Long officeId = personal.getOfficeId();
        if (officeId == null || officeId <= 0) {
            return Rv.error(EErrorCode.throwHallError);
        }
        if (personal.getOrderStatus() != EOrderStatus.waitingResponse.getType()) {
            return Rv.error(EErrorCode.throwHallStatusError);
        }
        //发送新订单通知
        producer.sendMsg(personal, MqConstant.NOTICE_NEW_ORDER);
        //抢单时间为行程开始前两个小时
        long endTime = personal.getAppointment().getTime() - Configuration.DELAY_ROB_BOOKING;
//        if (endTime < System.currentTimeMillis()) {
//            return Rv.error(EErrorCode.throwHallTimeError);
//        }
        String bookingKey = RedisPrefixConstant.ORDER_BOOKING + officeId + ":" + orderId;
        redisCommon.set(bookingKey, JSON.toJSONString(personal));
        redisCommon.addToZSet(RedisPrefixConstant.ORDER_TC_HALL + personal.getCityId(), bookingKey, endTime);
        //将甩单日志发送至mq
        log.info("甩单大厅的tokenUser:{}", TokenUtil.getTokenUser());
        operateLog(personal, TokenUtil.getTokenUser(), "将订单：" + personal.getOrderNo() + "放入甩单大厅", null);
        //更新甩单标志
        Integer update = oaCOrderPersonalMapper.updateThrowFlagByOrderId(1, personal.getOrderNo());
        if (update != 1) {
            throw PangException.create(EErrorCode.orderFailure);
        }
        return Rv.wrap();
    }

    @Override
    public List<String> getBookingOrder(String cityId, Long officeId) {
        //1.获取当前可抢订单ID
        long endTime = Long.MAX_VALUE;
        String hallKey = RedisPrefixConstant.ORDER_TC_HALL + cityId;
        Set<String> set = redisCommon.getFromZSet(hallKey, 0, endTime);

        List<String> datas;
        if (officeId != null) {
            Set<String> effectOrders = new HashSet<>();
            String officeKey = RedisPrefixConstant.ORDER_BOOKING + officeId + ":";

            for (String key : set) {
                if (key.contains(officeKey)) {
                    effectOrders.add(key);
                }
            }
            //2.获取当前可抢订单详情
            datas = redisCommon.multiGet(effectOrders);
        } else {
            datas = redisCommon.multiGet(set);
        }
        List<String> resList=new ArrayList<>();
        for (int i = 0; i < datas.size(); i++) {
            if(CheckUtil.strIsNotEmpty(datas.get(i))){
                resList.add(datas.get(i));
            }
        }
        return resList;
    }

    @Override
    public Rv robBookingOrder(long driverId, String orderId) {
        // FIXME 加强多线程问题测试
        if (CheckUtil.strIsEmpty(orderId)) {
            return Rv.error(EErrorCode.noData);
        }
        OaDUserInfo driverInfo = oaDUserInfoMapper.selectOne(Qw.create().eq(OaDUser.DRIVER_ID, driverId));
        if (driverInfo == null) {
            return Rv.error(EErrorCode.noData);
        }
        OaDUserOffice office = oaDUserOfficeMapper.selectOne(Qw.create().eq(OaDUserOffice.DRIVER_ID, driverId));
        if (office == null) {
            return Rv.error(EErrorCode.noData);
        }
        OaDUser oaDUser = oaDUserMapper.selectOne(Qw.create().eq(OaDUser.DRIVER_ID, driverId));
        if (null == oaDUser) {
            return Rv.error(EErrorCode.noData);
        }
        //抢单前 验证该司机一小时内有没有订单
        OaCOrderPersonal thisOrder = oaCOrderPersonalMapper.selectOne(new LambdaQueryWrapper<OaCOrderPersonal>().eq(OaCOrderPersonal::getOrderNo, orderId));
        List<OaCOrderPersonal> oaCOrderPersonals = oaCOrderPersonalMapper.selectList(new LambdaQueryWrapper<OaCOrderPersonal>()
                .eq(OaCOrderPersonal::getOrderStatus,3)
                .eq(OaCOrderPersonal::getDriverId,driverId)
        );
        List<OaCOrderPersonal> personals = new ArrayList<>();
        oaCOrderPersonals.stream().forEach(item -> {
            long appointmentTime = item.getAppointment().getTime();
            long thisOrderTime = thisOrder.getAppointment().getTime();
            if (Math.abs(appointmentTime - thisOrderTime) <= 1000 * 60 * 60 ) {
                personals.add(item);
            }
        });
        if(CheckUtil.objIsNotEmpty(personals)){
            log.info("{}该司机已存在1小时内的订单，无法抢单！",driverId);
            return Rv.error(EErrorCode.doubleOrderError);
        }
        //抢单前 判断该司机是不是该订单所属供应商旗下的司机
        OaDUserOffice dUserOffice= oaCOrderPersonalMapper.selectDriverOfficeByOrder(driverId,thisOrder.getOfficeId());
        if(CheckUtil.objIsEmpty(dUserOffice)){
            //为空 则订单和司机的供应商不一样
            log.info("{}该司机和该订单所属供应商不一致，无法抢单！",driverId);
            return Rv.error(EErrorCode.driverOfficeDifferenceError);
        }
        //抢单前判断该司机是否被拉黑
        if (oaDUser.getIsBlocked() == 1) {
            return Rv.error(EErrorCode.driverIsBlacklist);
        }
        Long officeId = office.getOfficeId();

        String cityId = driverInfo.getDriverCityId();

        Qw qw = Qw.create();
        qw.eq(OaCOrderPersonal.ORDER_NO, orderId);
        qw.eq(OaCOrderPersonal.CITY_ID, cityId);
        qw.eq(OaCOrderPersonal.ORDER_STATUS, 0);
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(qw);
        if (personal == null) {
            return Rv.error(EErrorCode.noData);
        }
        Long personalOfficeId = personal.getOfficeId();
        if (personalOfficeId == null || personalOfficeId.longValue() != officeId.longValue()) {
            return Rv.error(EErrorCode.noData);
        }
        // personal.setOfficeId(officeId);
        String hallKey = RedisPrefixConstant.ORDER_TC_HALL + cityId;
        String bookingKey = RedisPrefixConstant.ORDER_BOOKING + officeId + ":" + orderId;
        if (!redisCommon.delFromZSet(hallKey, bookingKey)) {
            //订单已被抢
            return Rv.error(EErrorCode.applyAmountOperateFailure);
        }

        Rv rv = handleOrder(personal, driverInfo, 0);
        if (rv.getCode() == EErrorCode.success.getValue()) {
            redisCommon.remove(bookingKey);

            //获取当前可抢订单详情
            Set<String> set = redisCommon.getFromZSet(hallKey, 0, Long.MAX_VALUE);
            Set<String> effectOrders = new HashSet<>();

            String officeKey = RedisPrefixConstant.ORDER_BOOKING + officeId + ":";
            for (String key : set) {
                if (key.startsWith(officeKey)) {
                    effectOrders.add(key);
                }
            }
            //2.获取当前可情
            List<String> datas = redisCommon.multiGet(set);
            rv.setData(datas);
            log.info("抢单接口中personal:{}", personal.getOrderNo());
            log.info("抢单接口中tokenUser:{}", TokenUtil.getTokenUser());
            //司机抢单成功将抢单日志发送至mq
            operateLog(personal, TokenUtil.getTokenUser(), "司机:" + oaDUser.getDriverName() + "抢到订单" + personal.getOrderNo(), null);
            Integer update = oaCOrderPersonalMapper.updateThrowFlagByOrderId(0, personal.getOrderNo());
            if (update != 1) {
                throw PangException.create(EErrorCode.orderFailure);
            }
        } else {
            long endTime = personal.getAppointment().getTime() - Configuration.DELAY_ROB_BOOKING;
            redisCommon.addToZSet(hallKey, bookingKey, endTime);
        }
        return rv;
    }

    @Override
    public Rv disBookingOrder(DisBookingOrderParam param) {
        String driverPhone = param.getDriverPhone();
        Long driverId = param.getDriverId();
        String orderId = param.getOrderId();
        if (CheckUtil.strIsEmpty(orderId)) {
            return Rv.error(EErrorCode.missingArg);
        }
        long userId = TokenUtil.getTokenUserId();
        if (userId <= 0) {
            return Rv.error(EErrorCode.authErr);
        }

        OaDUserInfo driverInfo = null;
        OaDUser driver = null;
        if (CheckUtil.strIsNotEmpty(driverPhone)) {
            driver = oaDUserMapper.selectOne(Qw.create().eq(OaDUser.DRIVER_PHONE, driverPhone));
            driverId = driver.getDriverId();
        }
        if (driver.getIsBlocked() == 1) {
            return Rv.error(EErrorCode.driverIsBlacklist);
        }
        if (CheckUtil.objIsNotEmpty(driverId) && driverId > 0) {
            driverInfo = oaDUserInfoMapper.selectOne(Qw.create().eq(OaDUserInfo.DRIVER_ID, driverId));
        } else {
            return Rv.error(EErrorCode.argCheckErr);
        }
        if (driverInfo == null) {
            return Rv.error(EErrorCode.argCheckErr);
        }

        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
        if (personal == null) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        //只针对携程和等待应答状态 验证最晚确认司机时间超时 -- 已取消此逻辑，若要回滚查看git版本 857a2e5b87f73a270b207f33c0d0cbd1f26bd37a

        int orderStatus = personal.getOrderStatus();
        if (orderStatus != EOrderStatus.waitingResponse.getType() && orderStatus != EOrderStatus.driverOrder.getType()) {
            return Rv.error(EErrorCode.disOrderStatuError);
        }

        Long officeId = personal.getOfficeId();
        if (officeId == null || officeId < 1) {
            return Rv.error(EErrorCode.authErr);
        }
//        OaSysUser manager = oaSysUserMapper.selectOne(Qw.create().eq(OaSysUser.OFFICE_ID, officeId));
//        if (manager == null) {
//            return Rv.error(EErrorCode.authErr);
//        }
//        Rv rv = handleOrder(personal, driverInfo, manager.getExpand4());
        //订单等级和司机等级校验
        Rv rv = handleOrder(personal, driverInfo, 0);
        if (rv.getCode() == EErrorCode.success.getValue()) {
            //删除可能存在的抢单信息
            String bookingKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + orderId;
            String hallKey = RedisPrefixConstant.ORDER_TC_HALL + personal.getCityId();
            redisCommon.delFromZSet(hallKey, bookingKey);
            redisCommon.remove(bookingKey);

            //向司机发送通知
            producer.sendMsg(personal, MqConstant.NOTICE_DIS_ORDER);
            //向司机发短信
            personal.setDriverId(driverInfo.getDriverId());
            producer.sendMsg(personal, MqConstant.NEW_ORDER_TO_DRIVER);
            Integer update = oaCOrderPersonalMapper.updateThrowFlagByOrderId(0, personal.getOrderNo());
            if (update != 1) {
                throw PangException.create(EErrorCode.orderFailure);
            }
            //将日志发送至mq
            operateLog(personal, TokenUtil.getTokenUser(), "将订单：" + personal.getOrderNo() + "指定给了司机：" + driver.getDriverName(), null);

        }
        return rv;
    }

    @Override
    public Rv suspendOrder(String orderNo) {
        if (CheckUtil.objIsEmpty(orderNo)) {
            return Rv.error(EErrorCode.missingArg);
        }
        //检查乘客订单
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderNo));
        if (CheckUtil.objIsEmpty(personal)) {
            return Rv.error(EErrorCode.penaltyOrderNone);
        }
        Integer cOrderStatus = personal.getOrderStatus();
        if (cOrderStatus == EOrderStatus.reservationLocation.getType()
                || cOrderStatus == EOrderStatus.driverArrived.getType()) {//前往预约地点 或者 司机已就位
            //更新乘客订单的状态 --- 司机已接单
            personal.setOrderStatus(EOrderStatus.driverOrder.getType());
            oaCOrderPersonalMapper.updateById(personal);
        } else {
            return Rv.error(EErrorCode.noSuspendOrder);
        }
        //检查司机订单
        OaDOrder oaDOrder = oaDOrderMapper.selectOne(Qw.create().eq(OaDOrder.ORDER_NO, orderNo));
        if (CheckUtil.objIsEmpty(oaDOrder)) {
            return Rv.error(EErrorCode.penaltyOrderNone);
        }
        Long driverId = oaDOrder.getDriverId();
        //更新司机订单的状态 --- 司机已接单
        oaDOrder.setOrderStatus(EOrderStatus.driverOrder.getType());
        oaDOrderMapper.updateById(oaDOrder);
        //查看司机的订单详细中的信息是否保存上了
        List<OaSysOrderDetails> oaSysOrderDetailsList = oaSysOrderDetailsMapper.selectList(Qw.create().
                eq(OaSysOrderDetails.ORDER_NO, orderNo).eq(OaSysOrderDetails.DRIVER_ID, driverId));
        if (oaSysOrderDetailsList.size() > 0) {
            for (OaSysOrderDetails oaSysOrderDetails : oaSysOrderDetailsList) {
                oaSysOrderDetailsMapper.deleteById(oaSysOrderDetails);
            }
        }
        operateLog(personal, TokenUtil.getTokenUser(), "已将该订单:" + personal.getOrderNo() + "置为挂起状态", null);
        // 删除缓存数据
        redisCommon.remove(RedisPrefixConstant.ORDER_OA_D_ORDER + orderNo);
        //解除司机锁定
        log.info("DRIVER_HISTORY 司机被释放了,司机当前订单号:[{}],当前订单状态:[{}],司机ID:[{}]", orderNo, cOrderStatus, driverId);
        orderCommon.destinationEmancipationDriver(false, driverId, orderNo);
        return Rv.wrap();
    }

    private Rv handleOrder(OaCOrderPersonal personal, OaDUserInfo driverInfo, int driverNumbers) {
        if (personal == null) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        if (driverInfo == null) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        Date dateTime = new Date();
        Long driverId = driverInfo.getDriverId();
        String cityId = driverInfo.getDriverCityId();
        String orderId = personal.getOrderNo();
        OaSysVehicle vehicle = oaSysVehicleMapper.selectOne(Qw.create().eq(OaSysVehicle.VEHICLE_OWNER_ID, driverId));
        if (vehicle == null) {
            return Rv.error(EErrorCode.noData);
        }
        //车辆等级校验
        if (!checkVehicleType(vehicle.getVehType(), personal.getVehicleType())) {
            return Rv.error(EErrorCode.throwOrderNoDriverLv);
        }
        Qw againQw = Qw.create();
        againQw.eq(OaDOrder.ORDER_NO, orderId);
        againQw.eq(OaDOrder.ORDER_STATUS, EOrderStatus.driverThrowOrder.getType());
        int againCount = oaDOrderMapper.selectCount(againQw);
        //已改派订单再次抢单校验
        if (againCount > 0) {
            return Rv.error(EErrorCode.robErrorForAgain);
        }
        //时间限制校验-限定时间= 预约时间+乘车时间+预留时间
        long appointmentTime = personal.getAppointment().getTime();
        long durationTime = personal.getDurationTime().intValue() * 60 * 1000L;//分钟数转换为毫秒
        long limitTime = appointmentTime + durationTime + Configuration.DELAY_EXTRA_TRIP;
        Qw limitQw = Qw.create();
        limitQw.eq(OaDOrder.DRIVER_ID, driverId);
        //limitQw.eq(OaDOrder.ORDER_STATUS, EOrderStatus.driverOrder.getType());
        limitQw.lt(OaDOrder.APPOINTMENT_TIME, limitTime);
        int limitCount = oaDOrderMapper.selectCount(limitQw);
        if (limitCount > 0) {
            //小于限制时间的订单数不为0，则表示该时段内已有其他订单
            return Rv.error(EErrorCode.robErrorForClash);
        }
        //钱包余额限制校验
        OaDWallet wallet = oaDWalletMapper.selectOne(Qw.create().eq(OaDWallet.DRIVER_ID, driverId));
        if (wallet != null && wallet.getWalletBalance().doubleValue() < Configuration.ROB_WALLET_LIMIT) {
            return Rv.error(EErrorCode.robErrorForWallet);
        }

        //1.保存订单状态
        personal.setDriverId(driverId);
        personal.setVehicleId(vehicle.getVehicleId());
        personal.setOrderStatus(EOrderStatus.driverOrder.getType());
        personal.setManagerRank(driverNumbers);//供应商人数-用于订单转派时供应商排位
        int res = oaCOrderPersonalMapper.updateById(personal);
        if (res < 1) {
            //订单已被抢
            return Rv.error(EErrorCode.applyAmountOperateFailure);
        }
        //2.将原有的司机接单数据置为删除状态
        oaDOrderMapper.delete(Qw.create().eq(OaDOrder.ORDER_NO, orderId));

        //3.状态同步
        StatusCallbackParam statusCallbackParam = new StatusCallbackParam();
        statusCallbackParam.setChannel(personal.getOrderChannel());
        statusCallbackParam.setOrder_id(orderId);
        statusCallbackParam.setDriver_id(driverId + "");
        statusCallbackParam.setStatus(personal.getOrderStatus());
        String str = redisCommon.getStr(RedisPrefixConstant.GPS_VEH_KEY_PREFIX + driverId);
        if (CheckUtil.strIsNotEmpty(str)) {
            OaDVehicleGps oaDVehicleGps = JSON.parseObject(str, OaDVehicleGps.class);
            statusCallbackParam.setDriver_lng(new BigDecimal(oaDVehicleGps.getLng()));
            statusCallbackParam.setDriver_lat(new BigDecimal(oaDVehicleGps.getLat()));
        }
        statusCallbackParam.setIsRetry(false);

        Rv rv = iDidiService.statusCallback(statusCallbackParam);
//        同步状态,如果失败,异步重试 ---删除原因
//           当前第三方平台（如携程，同程）的订单，在与司机做绑定时，第三方平台可能返还绑定不成功，但是在我们平台上，司机已经派下去了，可能导致运力浪费情况。
//           故这里应该改为同步动作，需要在第三方平台返还成功后，我们自有平台的订单派发才能生效
//        if (rv.getCode() != EErrorCode.success.getValue()) {
//            log.info("ORDER_HISTORY 订单号:[{}],确认上车接口,调用滴滴服务返回失败,进入重试机制,请求参数:[{}],调用滴滴服务返回值:[{}] ", personal.getOrderNo(), statusCallbackParam, rv);
//            producer.sendMsg(statusCallbackParam, MqConstant.STATUS_CALL_BACK_SYNC);
//        }
        if (rv.getCode() != EErrorCode.success.getValue()) {
            log.info("第三方平台同步返回失败!");
            personal.setDriverId(null);
            personal.setVehicleId(null);
            personal.setOrderStatus(EOrderStatus.waitingResponse.getType());
            personal.setManagerRank(0);//供应商人数-用于订单转派时供应商排位
            oaCOrderPersonalMapper.updateById(personal);
            return Rv.error(EErrorCode.disOrderStatuError);
        }

        //3.开启2小时倒计时
        long endTime = personal.getAppointment().getTime() - Configuration.DELAY_START_TRIP;
        //long endTime = System.currentTimeMillis() + 1000;
        redisCommon.addToZSet(RedisPrefixConstant.ORDER_TC_ZSET2, orderId, endTime);

        //4.创建司机订单
        Long personalId = personal.getPersonalId();
        OaDOrder oaDOrder = oaDOrderMapper.queryDriverOrderById(driverId, orderId, personalId);
        if (oaDOrder == null) {
            oaDOrder = new OaDOrder();
            oaDOrder.setUserOrderId(String.valueOf(personalId));
            oaDOrder.setOrderType(personal.getOrderType());
            oaDOrder.setTotalCost(personal.getTotalFee());
            oaDOrder.setDrawFee(personal.getDrawFee());
            oaDOrder.setDeleted(0);
            oaDOrder.setDriverId(driverId);
            oaDOrder.setStriveTime(dateTime);
            oaDOrder.setAppointmentTime(personal.getAppointment());
            oaDOrder.setPassengerPhone(personal.getPassengerPhone());
            oaDOrder.setFlat(personal.getStartLat());
            oaDOrder.setFlng(personal.getStartLng());
            oaDOrder.setTlat(personal.getEndLat());
            oaDOrder.setTlng(personal.getEndLng());
            oaDOrder.setPickPassengersFlng(personal.getStartLng());
            oaDOrder.setPickPassengersFlat(personal.getStartLat());
            oaDOrder.setOrderStatus(personal.getOrderStatus());
            oaDOrder.setVehicleId(personal.getVehicleId());
            oaDOrder.setUpdateTime(dateTime);
            oaDOrder.setUpdateUser(driverId);
            oaDOrder.setCreateTime(dateTime);
            oaDOrder.setCreateUser(driverId);
            oaDOrder.setOrderNo(orderId);
            res = oaDOrderMapper.insert(oaDOrder);
            if (res < 1) {
                return Rv.error(EErrorCode.applyAmountOperateFailure);
            }
        } else {
            //对供应商转派时多次指派同一司机进行处理
            oaDOrderMapper.updateDriverOrderById(dateTime, personal.getOrderStatus(), driverId, orderId, personalId);
        }
        return Rv.wrap();
    }

    private Rv handleCharterOrder(OaCOrderPersonal personal, OaDUserInfo driverInfo, int driverNumbers, OaDOrderCharteredDetail charteredDetail) {
        if (personal == null) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        if (driverInfo == null) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        Date dateTime = new Date();
        Long driverId = driverInfo.getDriverId();
        String cityId = driverInfo.getDriverCityId();
        String orderId = personal.getOrderNo();
        OaSysVehicle vehicle = oaSysVehicleMapper.selectOne(Qw.create().eq(OaSysVehicle.VEHICLE_OWNER_ID, driverId));
        if (vehicle == null) {
            return Rv.error(EErrorCode.noData);
        }
        //车辆等级校验
        if (!checkVehicleType(vehicle.getVehType(), personal.getVehicleType())) {
            return Rv.error(EErrorCode.throwOrderNoDriverLv);
        }
        Qw againQw = Qw.create();
        againQw.eq(OaDOrder.ORDER_NO, orderId);
        againQw.eq(OaDOrder.ORDER_STATUS, EOrderStatus.driverThrowOrder.getType());
        int againCount = oaDOrderMapper.selectCount(againQw);
        //已改派订单再次抢单校验
        if (againCount > 0) {
            return Rv.error(EErrorCode.robErrorForAgain);
        }
        //钱包余额限制校验
        OaDWallet wallet = oaDWalletMapper.selectOne(Qw.create().eq(OaDWallet.DRIVER_ID, driverId));
        if (wallet != null && wallet.getWalletBalance().doubleValue() < Configuration.ROB_WALLET_LIMIT) {
            return Rv.error(EErrorCode.robErrorForWallet);
        }
        //1.保存订单状态
        personal.setDriverId(driverId);
        personal.setVehicleId(vehicle.getVehicleId());
        personal.setOrderStatus(EOrderStatus.driverOrder.getType());
        personal.setManagerRank(driverNumbers);//供应商人数-用于订单转派时供应商排位
        int res = oaCOrderPersonalMapper.updateById(personal);
        if (res < 1) {
            //订单已被抢
            return Rv.error(EErrorCode.applyAmountOperateFailure);
        }
        //2.将原有的司机接单数据置为删除状态
        int delete = oaDOrderMapper.delete(Qw.create().eq(OaDOrder.ORDER_NO, orderId).eq(OaDOrder.APPOINTMENT_TIME, charteredDetail.getOrderDate()));
        /**
         * 3.状态同步
         * 判断是否是第一天，只推送第一天的司机变动
         */
        if (personal.getAppointment().equals(charteredDetail.getOrderDate())){
            //根据日期判断是否是第一天
                StatusCallbackParam statusCallbackParam = new StatusCallbackParam();
                statusCallbackParam.setChannel(personal.getOrderChannel());
                statusCallbackParam.setOrder_id(orderId);
                statusCallbackParam.setDriver_id(driverId + "");
                statusCallbackParam.setOrderTpye(7);
                statusCallbackParam.setStatus(personal.getOrderStatus());
                String str = redisCommon.getStr(RedisPrefixConstant.GPS_VEH_KEY_PREFIX + driverId);
                if (CheckUtil.strIsNotEmpty(str)) {
                    OaDVehicleGps oaDVehicleGps = JSON.parseObject(str, OaDVehicleGps.class);
                    statusCallbackParam.setDriver_lng(new BigDecimal(oaDVehicleGps.getLng()));
                    statusCallbackParam.setDriver_lat(new BigDecimal(oaDVehicleGps.getLat()));
                }
                statusCallbackParam.setIsRetry(false);

                Rv rv = iDidiService.statusCallback(statusCallbackParam);
                log.info("包车订单指派司机成功回调的Rv:",rv);
                if (rv.getCode() != EErrorCode.success.getValue()) {
                    log.info("第三方平台同步返回失败!");
                    personal.setDriverId(null);
                    personal.setVehicleId(null);
                    personal.setOrderStatus(EOrderStatus.waitingResponse.getType());
                    personal.setManagerRank(0);//供应商人数-用于订单转派时供应商排位
                    oaCOrderPersonalMapper.updateById(personal);
                    return Rv.error(EErrorCode.disOrderStatuError);
                }
        }
        //3.开启2小时倒计时
        long endTime = personal.getAppointment().getTime() - Configuration.DELAY_START_TRIP;
        //long endTime = System.currentTimeMillis() + 1000;
        redisCommon.addToZSet(RedisPrefixConstant.ORDER_TC_ZSET2, orderId, endTime);

        //4.创建司机订单
        Long personalId = personal.getPersonalId();
        Date orderDate = charteredDetail.getOrderDate();
        OaDOrder oaDOrder = oaDOrderMapper.queryDriveCharterOrderById(driverId, orderId, personalId, orderDate);
        if (oaDOrder == null) {
            oaDOrder = new OaDOrder();
            oaDOrder.setUserOrderId(String.valueOf(charteredDetail.getId()));
            oaDOrder.setOrderType(personal.getOrderType());
            oaDOrder.setTotalCost(charteredDetail.getPackageCost());
            oaDOrder.setDrawFee(personal.getDrawFee());
            oaDOrder.setDeleted(0);
            oaDOrder.setDriverId(driverId);
            oaDOrder.setStriveTime(dateTime);
            oaDOrder.setAppointmentTime(charteredDetail.getOrderDate());
            oaDOrder.setPassengerPhone(personal.getPassengerPhone());
            oaDOrder.setFlat(charteredDetail.getFlat());
            oaDOrder.setFlng(charteredDetail.getFlng());
            oaDOrder.setTlat(charteredDetail.getTlat());
            oaDOrder.setTlng(charteredDetail.getTlng());
            oaDOrder.setOrderStatus(EOrderStatus.driverOrder.getType());
            oaDOrder.setVehicleId(Long.valueOf(charteredDetail.getVehicleId()));
            oaDOrder.setUpdateTime(dateTime);
            oaDOrder.setUpdateUser(driverId);
            oaDOrder.setCreateTime(dateTime);
            oaDOrder.setCreateUser(TokenUtil.getTokenUserId());
            oaDOrder.setOrderNo(personal.getOrderNo());
            res = oaDOrderMapper.insert(oaDOrder);
            if (res < 1) {
                return Rv.error(EErrorCode.applyAmountOperateFailure);
            }
        } else {
            //对供应商转派时多次指派同一司机进行处理
            oaDOrderMapper.updateDriverOrderById(dateTime, personal.getOrderStatus(), driverId, orderId, personalId);
        }
        return Rv.wrap();
    }

    private boolean checkVehicleType(int driverVehicletype, int orderVehicleType) {
        EVehicleType vehicleType = EVehicleType.findVehType(orderVehicleType);
        switch (vehicleType) {
            case vehTypeEconomic: {
                //经济型订单所有车都可以接
                return true;
            }
            case vehTypeComfortable: {
                if (driverVehicletype == EVehicleType.vehTypeEconomic.getValue()) {
                    return false;
                } else {
                    //舒适型订单只有舒适，商务和豪华车可接单
                    return true;
                }
            }
            case vehTypeBusiness: {
                if (driverVehicletype == EVehicleType.vehTypeBusiness.getValue()) {
                    //商务型订单只有商务车可接单
                    return true;
                } else {
                    return false;
                }
            }
            case vehTypeLuxury: {
                if (driverVehicletype == EVehicleType.vehTypeLuxury.getValue()) {
                    //豪华型订单只有豪华车可接单
                    return true;
                } else {
                    return false;
                }
            }
            default: {
                return false;
            }
        }
    }

    @Override
    public Rv throwBookingOrder(DisBookingOrderParam param) {
        String orderId = param.getOrderId();
        if (CheckUtil.strIsEmpty(orderId)) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        Long userId = TokenUtil.getTokenUserId();
        if (userId == null || userId < 1) {
            return Rv.error(EErrorCode.authErr);
        }
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderId));
        if (personal == null) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        int orderStatus = personal.getOrderStatus();
        if (orderStatus != EOrderStatus.waitingResponse.getType() && orderStatus != EOrderStatus.driverOrder.getType()) {
            return Rv.error(EErrorCode.throwOrderStatuError);
        }
        Long officeId = personal.getOfficeId();
        int rank = personal.getManagerRank();
        if (officeId == null || officeId == 0 || rank == 0) {
            //司机抢单后需转派
            rank = Integer.MAX_VALUE;
        }

        //1.查找供应商-司机数载当前供应商之后的供应商
        QueryWrapper<OaSysUser> qw = new QueryWrapper<>();
        qw.lt(OaSysUser.EXPAND4, rank);//小于等于当前司机数
        qw.gt(OaSysUser.EXPAND4, 0);//大于0
        qw.orderByDesc(OaSysUser.EXPAND4);
        List<OaSysUser> users = oaSysUserMapper.selectList(qw);
        if (users.isEmpty()) {
            return Rv.error(EErrorCode.throwOrderNoManager);
        }
        OaSysUser user = null;
        for (OaSysUser muser : users) {
            if (muser.getOfficeId() != officeId) {
                user = muser;
                break;
            }
        }
        if (user == null) {
            return Rv.error(EErrorCode.throwOrderNoManager);
        }

        //2.删除可能存在的抢单信息
        String bookingOrderKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + personal.getOrderNo();
        String bookingHallKey = RedisPrefixConstant.ORDER_TC_HALL + personal.getCityId();
        redisCommon.delFromZSet(bookingHallKey, bookingOrderKey);
        redisCommon.remove(bookingOrderKey);

        //3.将订单派给新的供应商
        personal.setOfficeId(user.getOfficeId());
        personal.setManagerRank(user.getExpand4());
        int res = oaCOrderPersonalMapper.updateById(personal);
        if (res < 1) {
            Rv.error(EErrorCode.applyAmountOperateFailure);
        }
        return Rv.wrap();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Rv disBookingOrderToManager(DisBookingOrderParam param) {
        String orderId = param.getOrderId();
        if (CheckUtil.strIsEmpty(orderId)) {
            return Rv.error(EErrorCode.argCheckErr);
        }
        Long userId = TokenUtil.getTokenUserId();
        if (userId == null || userId < 1) {
            return Rv.error(EErrorCode.authErr);
        }
        Long officeId = oaSysUserMapper.checkUserAuth(userId);
        if (officeId == null || officeId < 1) {
            return Rv.error(EErrorCode.authErr);
        }
        AssertUtil.isFalse(officeId.equals(param.getOfficeId()), "不能将订单指派给自己");
        OaCOrderPersonal personal =
                oaCOrderPersonalMapper.selectOne(new LambdaQueryWrapper<OaCOrderPersonal>().eq(OaCOrderPersonal::getOrderNo, orderId));
        if (personal == null) {
            return Rv.error(EErrorCode.orderNotFound);
        }

        personal.setPreOfficeId(param.getOfficeId());
        int res = oaCOrderPersonalMapper.updateById(personal);
        if (res < 1) {
            Rv.error(EErrorCode.applyAmountOperateFailure);
        }
        // mq写日志
        operateLog(personal, TokenUtil.getTokenUser(), "将订单:" + personal.getOrderNo() + "指派给了供应商:%s", (des) -> {
            OaSysOffice oaSysOffice = oaSysOfficeMapper.selectById(personal.getPreOfficeId());
            AssertUtil.notNull(oaSysOffice, "机构:%d 不存在", personal.getPreOfficeId());
            return String.format(des, oaSysOffice.getName());
        });
        return Rv.wrap();
    }

    @Override
    public Rv startMyBookingOrder(long driverId, String orderNo, EOrderStatus orderStatusParam) {
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderNo));
        OaDOrder oaDOrder = null;
        if (personal.getOrderType() == 7) {
            oaDOrder = oaDOrderMapper.selectOne(Qw.create().eq(OaDOrder.ORDER_NO, orderNo).
                    between(OaDOrder.APPOINTMENT_TIME, DateUtil.getDateDay() + " 00:00:00", DateUtil.getDateDay() + " 23:59:59"));
        } else {
            oaDOrder = oaDOrderMapper.selectById(orderNo);
        }
        if (CheckUtil.objIsEmpty(oaDOrder) || CheckUtil.objIsEmpty(personal)) {
            throw PangException.create(EErrorCode.noData);
        }
        long currentTime = System.currentTimeMillis();
        if ((personal.getAppointment().getTime() - currentTime) > 2 * 60 * 60 * 1000) {
            return Rv.error(EErrorCode.startTripError);
        }
//            String str = redisCommon.getStr(RedisPrefixConstant.ORDER_USER + orderNo);
//            if (CheckUtil.strIsEmpty(str) && personal.getOrderStatus() == EOrderStatus.driverOrder.getType()) {
        int orderStatus = personal.getOrderStatus();
        if (orderStatus == EOrderStatus.driverOrder.getType() || personal.getOrderType()==7) {
            OaDUserInfo oaDUserInfo = oaDUserInfoMapper.selectOne(Qw.create().eq(OaDUserInfo.DRIVER_ID, personal.getDriverId()));
            if (oaDUserInfo.getIsOrder() != 0) {
                return Rv.error(EErrorCode.startTrapStatusError);
            }

            if (personal.getOrderChannel() == EOrderChannelType.xiecheng.getType()) {
                //检查当前订单状态
                StatusCallbackParam param = new StatusCallbackParam();
                param.setOrder_id(personal.getOrderNo());
                param.setChannel(personal.getOrderChannel());
                param.setStatus(EOrderStatus.orderStatusCheck.getType());
                Rv rv = Rv.wrap();
                //TODO 测试使用
                if (personal.getOrderType() != 7) {
                    rv = iDidiService.statusCallback(param);
                }
                if (rv.getCode() != EErrorCode.success.getValue()) {
                    return rv;
                }
            }
            // 当前无正在执行的订单，立即开启行程
            personal.setOrderStatus(orderStatusParam.getType());
            oaCOrderPersonalMapper.updateById(personal);
            oaDOrder.setOrderStatus(orderStatusParam.getType());
            UpdateWrapper<OaDOrder> updateWrapper=new UpdateWrapper<>();
            updateWrapper.eq(OaDOrder.ORDER_NO,orderNo);
            updateWrapper.eq(OaDOrder.APPOINTMENT_TIME,oaDOrder.getAppointmentTime());
            oaDOrderMapper.update(oaDOrder,updateWrapper);

            NettyDriverOrderInfo nettyDriverOrderInfo = new NettyDriverOrderInfo();
            nettyDriverOrderInfo.setOrderNo(personal.getOrderNo());
            nettyDriverOrderInfo.setStartAddress(personal.getStartAddress());
            nettyDriverOrderInfo.setEndAddress(personal.getEndAddress());
            nettyDriverOrderInfo.setCallVehType(MessageConstant.ORDER_TYPE_ONE);
            nettyDriverOrderInfo.setStartLat(personal.getStartLat());
            nettyDriverOrderInfo.setStartLng(personal.getStartLng());
            nettyDriverOrderInfo.setEndLat(personal.getEndLat());
            nettyDriverOrderInfo.setEndLng(personal.getEndLng());
            nettyDriverOrderInfo.setOrderStatus(personal.getOrderStatus());
            //猎鹰需要ID
            nettyDriverOrderInfo.setTid(1L);
            nettyDriverOrderInfo.setGpsId(1639268888477696L);
            nettyDriverOrderInfo.setServiceId(0L);
            nettyDriverOrderInfo.setDistance(personal.getMilageDistance() + "");
            nettyDriverOrderInfo.setDistanceTime(personal.getDurationTime() + "");
            nettyDriverOrderInfo.setMsg("来订单了,据您" + 100 + "从" + nettyDriverOrderInfo.getStartAddress() + "到" + nettyDriverOrderInfo.getEndAddress() + "请尽快前往乘客上车地点接送乘客");
            nettyDriverOrderInfo.setOrderTypeInt(personal.getOrderType());

            String orderVeh = RedisPrefixConstant.ORDER_VEH + driverId;
            redisCommon.set(orderVeh, JSON.toJSONString(nettyDriverOrderInfo));

            //关联当前订单号到司机信息去
            oaDUserInfo.setIsOrder(EDriverStatus.isOrderYes.getValue());
            oaDUserInfo.setCurrentOrderNo(personal.getOrderNo());
            if (oaDUserInfoMapper.updateById(oaDUserInfo) > 0) {
                log.info("ORDER_HISTORY 订单号:[{}],开始行程(END)  ", personal.getOrderNo());
                redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET2, orderNo);
                return Rv.wrap();
            } else {
                // TODO 订单异常
                log.error("订单异常，无法关联当前订单号到司机");
                redisCommon.addToZSet(RedisPrefixConstant.ORDER_TC_ZSET2, orderNo, System.currentTimeMillis());
                return Rv.error(EErrorCode.unkown);
            }
        } else if (orderStatus > EOrderStatus.driverOrder.getType() || orderStatus <= EOrderStatus.duringTrip.getType()) {
            return Rv.error(EErrorCode.startTrapStatusError);
        } else {
            redisCommon.addToZSet(RedisPrefixConstant.ORDER_TC_ZSET2, orderNo, System.currentTimeMillis());
            return Rv.error(EErrorCode.unkown);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderAccept(String orderNo) {
        //  TODO 需要保证接口幂等性,升级redis会导致注册中心注册失败,暂无解决方案
        Long officeId = oaSysUserMapper.checkUserAuth(TokenUtil.getTokenUser().getTokenUserId());
        if (officeId == null || officeId < 1) {
            throw new PangException(EErrorCode.authErr);
        }
        //查询/校验订单
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(new LambdaQueryWrapper<OaCOrderPersonal>()
                .eq(OaCOrderPersonal::getOrderNo, orderNo));
        AssertUtil.notNull(personal, "当前选择订单不存在");
        AssertUtil.gtZero(personal.getPreOfficeId(), "当前选择订单已被处理");
        AssertUtil.isTrue(EOrderStatus.waitingResponse.getType().equals(personal.getOrderStatus())
                || EOrderStatus.driverOrder.getType().equals(personal.getOrderStatus()), "订单已被处理(被指派/抢单/取消)");
        Long oldOfficeId = personal.getOfficeId();
        //1.删除可能存在的抢单信息
        String bookingOrderKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + personal.getOrderNo();
        String bookingHallKey = RedisPrefixConstant.ORDER_TC_HALL + personal.getCityId();
        redisCommon.delFromZSet(bookingHallKey, bookingOrderKey);
        redisCommon.remove(bookingOrderKey);
        List<OaSysUser> driverManager = oaSysUserMapper.selectList(Qw.create().eq(OaSysUser.OFFICE_ID, personal.getOfficeId()));
        if (CollectionUtils.isEmpty(driverManager)) {
            throw new PangException(EErrorCode.argCheckErr);
        }
        //2.将订单派给新的供应商
        personal.setManagerRank(driverManager.get(NumberUtils.INTEGER_ZERO).getExpand4());
        //修改订单状态
        personal.setOfficeId(personal.getPreOfficeId()).setPreOfficeId(NumberUtils.LONG_ZERO);
        //处理司机已接单再转供应商的情况
        if (personal.getOrderStatus().equals(EOrderStatus.driverOrder.getType())) {
            personal.setOrderStatus(EOrderStatus.waitingResponse.getType());
            personal.setDriverId(0L);
            personal.setVehicleId(0L);
            personal.setManagerRank(0);
        }
        int res = oaCOrderPersonalMapper.updateById(personal);
        if (res < 1) {
            Rv.error(EErrorCode.applyAmountOperateFailure);
        }
        //供应商接收后 司机抢单无效
        OaDOrder dOrder = oaDOrderMapper.selectOne(new LambdaQueryWrapper<OaDOrder>().eq(OaDOrder::getOrderNo,orderNo));
        if(CheckUtil.objIsNotEmpty(dOrder)){
            UpdateWrapper<OaDOrder> oaDOrderUpdateWrapper = new UpdateWrapper<>();
            oaDOrderUpdateWrapper.eq(OaDOrder.ORDER_NO,dOrder.getOrderNo()).set(OaDOrder.DELETED,1);
            int update = oaDOrderMapper.update(dOrder,oaDOrderUpdateWrapper);
            if (update < 1) {
                log.info("供应商接收后,司机抢单无效设置失败！");
            }
        }
        //写入日志放入mq
        operateLog(personal, TokenUtil.getTokenUser(), " 接收了供应商:%s 的转单请求,订单编号:" + personal.getOrderNo(), (des) -> {
            OaSysOffice oaSysOffice = oaSysOfficeMapper.selectById(oldOfficeId);
            AssertUtil.notNull(oaSysOffice, "机构:%d 不存在", oldOfficeId);
            return String.format(des, oaSysOffice.getName());
        });
        return true;
    }

    @Override
    public List<OrderLogMo> orderTracking(String orderNo) {
        return mongoTemplate.find(new Query(Criteria.where("orderNo").is(orderNo)), OrderLogMo.class);
    }

    /**
     * 订单操作日志入库
     **/
    private void operateLog(OaCOrderPersonal personal, TokenUser tokenUser, String description, Function<String, Object> function) {
        threadPoolExecutor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    if (CheckUtil.objIsEmpty(tokenUser)) {
                        throw PangException.create(EErrorCode.nullData);
                    }
                    String username = "";
                    if (CheckUtil.objIsNotEmpty(tokenUser.getRoles())) {
                        OaSysUser user = userMapper.selectOne(Qw.create().eq(OaSysUser.SYS_USER_ID, tokenUser.getTokenUserId()));
                        if (null == user) {
                            throw PangException.create(EErrorCode.nullData);
                        }
                        username = StringUtils.isBlank(user.getName()) ? user.getLoginName() : user.getName();
                    } else {
                        OaDUser oaDUser = oaDUserMapper.selectById(tokenUser.getTokenUserId());
                        if (null == oaDUser) {
                            throw PangException.create(EErrorCode.nullData);
                        }
                        username = StringUtils.isBlank(oaDUser.getDriverName()) ? "ID:" + tokenUser.getTokenUserId() + "未设置名字" : oaDUser.getDriverName();
                    }
                    OrderLogMo orderLogVO = OrderLogMo
                            .builder()
                            .id(IDUtil.nextId())
                            .orderNo(personal.getOrderNo())
                            .officeId(personal.getOfficeId())
                            .preOfficeId(personal.getPreOfficeId())
                            .orderStatus(personal.getOrderStatus())
                            .operatorId(tokenUser.getTokenUserId())
                            .operator(username)
                            .operateTime(LocalDateTime.now())
                            .description(username + " " + (Objects.nonNull(function) ? function.apply(description) : description))
                            .build();
                    producer.sendMsg(orderLogVO, LOG_OPERATE_ORDER);
                } catch (Exception e) {
                    log.error("发送订单日志异常:", e);
                }
            }
        });
    }
}
